#ifndef ITERATOR_H_INCLUDED
#define ITERATOR_H_INCLUDED

#include "Vector.h"
#include "LinkedList.h"
#include "Deque.h"

namespace CEngine {

template<class Element, class key>
class Iterator {
    public:

        ///
        ///Constructors
        ///

        Iterator(void);

        Iterator(const typename Vector<Element>::VectorIterator& iterator);

        Iterator(const typename LinkedList<Element>::ListIterator& iterator);

        Iterator(const typename Deque<Element>::DequeIterator& iterator);

        ///
        ///Assignment operators.
        ///

        Iterator&
        operator= (const typename Vector<Element>::VectorIterator& iterator);

        Iterator&
        operator= (const typename LinkedList<Element>::ListIterator& iterator);

        Iterator&
        operator= (const typename Deque<Element>::DequeIterator& iterator);

        ///
        ///Access operators.
        ///

        ///Random access operator. Returns a reference to an element, and sets it as the current position.
        ///First element is 0. Logs an error if position is out of range, and returns the last element.
        Element*
        operator[](U64 position);

        ///incremental access operator. Returns a reference to an element.
        ///increments up to then holds at the last element. ++vector and vector++ are valid.
        Element*
        operator++(void);

        ///decremental access operator. Returns a reference to an element.
        ///decrements down to then holds on the first element. --vector and vector-- are valid.
        Element*
        operator--(void);

        ///Returns a pointer to the current element.
        operator Element*(void) const;

        ///
        ///Comparison operators.
        ///

        ///Iterators
        bool
        operator==(const Iterator& iterator) const;

        bool
        operator!=(const Iterator& iterator) const;

        bool
        operator>(const Iterator& iterator) const;

        bool
        operator<(const Iterator& iterator) const;

        bool
        operator>=(const Iterator& iterator) const;

        bool
        operator<=(const Iterator& iterator) const;

        ///Integers
        bool
        operator==(const I64 number) const;

        bool
        operator!=(const I64 number) const;

        bool
        operator>(const I64 number) const;

        bool
        operator<(const I64 number) const;

        bool
        operator>=(const I64 number) const;

        bool
        operator<=(const I64 number) const;

        ///Vectors
        bool
        operator==(const typename Vector<Element>::VectorIterator& iterator) const;

        bool
        operator!=(const typename Vector<Element>::VectorIterator& iterator) const;

        bool
        operator>(const typename Vector<Element>::VectorIterator& iterator) const;

        bool
        operator<(const typename Vector<Element>::VectorIterator& iterator) const;

        bool
        operator>=(const typename Vector<Element>::VectorIterator& iterator) const;

        bool
        operator<=(const typename Vector<Element>::VectorIterator& iterator) const;

        ///LinkedLists
        bool
        operator==(const typename LinkedList<Element>::ListIterator& iterator) const;

        bool
        operator!=(const typename LinkedList<Element>::ListIterator& iterator) const;

        bool
        operator>(const typename LinkedList<Element>::ListIterator& iterator) const;

        bool
        operator<(const typename LinkedList<Element>::ListIterator& iterator) const;

        bool
        operator>=(const typename LinkedList<Element>::ListIterator& iterator) const;

        bool
        operator<=(const typename LinkedList<Element>::ListIterator& iterator) const;

        ///Deques
        bool
        operator==(const typename Deque<Element>::DequeIterator& iterator) const;

        bool
        operator!=(const typename Deque<Element>::DequeIterator& iterator) const;

        bool
        operator>(const typename Deque<Element>::DequeIterator& iterator) const;

        bool
        operator<(const typename Deque<Element>::DequeIterator& iterator) const;

        bool
        operator>=(const typename Deque<Element>::DequeIterator& iterator) const;

        bool
        operator<=(const typename Deque<Element>::DequeIterator& iterator) const;

        ///
        ///Arithmetic operators.
        ///

        Element*
        operator+(const I64 number) const;

        Element*
        operator-(const I64 number) const;

        Element*
        operator-(const Iterator& iterator) const;

        Iterator&
        operator+=(const I64 number);

        Iterator&
        operator-=(const I64 number);

        ///
        ///Functions.
        ///

        ///Returns the iterator's position as an integer,
        U64
        getPosition(void) const;

    private:

        enum ContainerType {
            None,
            Vector,
            LinkedList,
            Deque,
            Queue,
            BinarySearchTree,
            PriorityQueue
        } type;

        union {
            struct {
                CEngine::Vector<Element>* basePointer;
                Element* currentElement;
            } vector;
            struct {
                CEngine::LinkedList<Element>* basePointer;
                typename CEngine::LinkedList<Element>::Link* currentElement;
                U64 position;
            } list;
            struct {
                CEngine::Deque<Element>* basePointer;
                Element** currentArray;
                Element* startElement;
                Element* currentElement;
                Element* endElement;
                U64 position;
            } deque;
        } iteratorData ;

        inline void
        dequeRandomAccess(void);

        friend class LinkedList<Element>;
};

}

#include "IteratorCore.h"
#include "IteratorVector.h"
#include "IteratorList.h"
#include "IteratorDeque.h"

#endif // ITERATOR_H_INCLUDED
